package com.youlu.campus.service.system.impl;

import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.entity.VO.req.SystemIpLimitQueryVO;
import com.youlu.campus.entity.system.SystemIpLimit;
import com.youlu.campus.service.system.SystemIpLimitService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;

@Slf4j
@Service
public class SystemIpLimitServiceImpl implements SystemIpLimitService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    private String SYSTEM_IP_LIMIT_KEY = "com.luyou.ip.limit..:";

    @Override
    public boolean existIp(String ip) {
        Object o = redisTemplate.opsForHash().get(SYSTEM_IP_LIMIT_KEY, ip);
        if (Objects.isNull(o)) {
            return false;
        }
        return true;
    }

    @Override
    public boolean update(SystemIpLimit req) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(req.getId()));
        boolean toUpdate = false;
        Update update = new Update();
        if (StringUtils.isNotBlank(req.getDesc())) {
            update.set("desc", req.getDesc());
            toUpdate = true;
        }
        if (StringUtils.isNotBlank(req.getOperator())) {
            update.set("operator", req.getOperator());
            toUpdate = true;
        }
        if (StringUtils.isNotBlank(req.getType())) {
            update.set("type", req.getType());
            toUpdate = true;
        }
        if (StringUtils.isNotBlank(req.getCountry())) {
            update.set("country", req.getCountry());
            toUpdate = true;
        }
        if (StringUtils.isNotBlank(req.getLocation())) {
            update.set("location", req.getLocation());
            toUpdate = true;
        }
        if (StringUtils.isNotBlank(req.getComments())) {
            update.set("comments", req.getComments());
            toUpdate = true;
        }
        if (toUpdate) {
            update.set("updatedTime", new Date());
            UpdateResult re = mongoTemplate.updateFirst(query, update, SystemIpLimit.class);
            return re.getModifiedCount() > 0 ? true : false;
        }
        return false;
    }

    @Override
    public SystemIpLimit create(SystemIpLimit req) {
        req.setId(null);
        req.setCreatedTime(new Date());
        redisTemplate.opsForHash().putIfAbsent(SYSTEM_IP_LIMIT_KEY, req.getIp(), "1");
        return mongoTemplate.insert(req);
    }

    @Override
    public boolean delete(String id) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(id));
        Update update = new Update();
        update.set("deleted", true);
        UpdateResult re = mongoTemplate.updateFirst(query, update, SystemIpLimit.class);
        SystemIpLimit s = this.findOne(id);
        if (Objects.nonNull(s) && StringUtils.isNotBlank(s.getIp())) {
            redisTemplate.opsForHash().delete(SYSTEM_IP_LIMIT_KEY, s.getIp());
        }
        return re.getModifiedCount() > 0 ? true : false;
    }

    @Override
    public Page<SystemIpLimit> list(SystemIpLimitQueryVO req) {
        Query query = new Query();
        query.addCriteria(Criteria.where("deleted").ne(Boolean.TRUE));
        if (StringUtils.isNotBlank(req.getIp())) {
            query.addCriteria(Criteria.where("ip").is(req.getIp()));
        }
        if (StringUtils.isNotBlank(req.getDesc())) {
            Pattern compile = Pattern.compile("^.*" + req.getDesc() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("desc").is(compile));
        }
        if (StringUtils.isNotBlank(req.getCountry())) {
            query.addCriteria(Criteria.where("country").is(req.getCountry()));
        }
        long count = mongoTemplate.count(query, SystemIpLimit.class);
        PageRequest pageRequest = PageRequest.of(req.getPage() - 1, req.getPageSize());
        Sort sort = Sort.by(Sort.Direction.DESC, "createdTime");
        query.with(sort);
        List<SystemIpLimit> infos = mongoTemplate.find(query.with(pageRequest), SystemIpLimit.class);
        return PageableExecutionUtils.getPage(infos, pageRequest, () -> count);
    }

    @Override
    public SystemIpLimit findOne(String id) {
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(id));
        return mongoTemplate.findOne(query, SystemIpLimit.class);
    }
}
